package slhs.tempo.TableAnalyzer;

import java.awt.Color;
import java.awt.Font;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import org.mlc.swing.layout.LayoutConstraintsManager;

import slhs.tempo.scriptGenerator.PanelHandler;
import slhs.tempo.scriptGenerator.UtilityConstants;

public class FilterControlsPanelHandler extends JPanel implements PanelHandler, FocusListener {

    private static final String FILTER_CONTROLS_PANEL_LAYOUT_XML_FILE = "FILTERS_CONTROL_PANEL_LAYOUT.xml";
    private static final String REACTION_TIME_COLUMN_IDENTIFIER = "Reaction Time";
    private static final String RESPONSE_COLUMN_IDENTIFIER = "Response";
    private static final String CORRECT_RESPONSE_COLUMN_IDENTIFIER = "Correct Response";
    private static final String SEARCH_TIP = "Seperate search terms by comma";
    private static final String IGNORE_PROBES = "Ignore probes";
    private static final String NON_EXP_ITEMS_FILTER = "Non Exp Items Filter";
    private static final String BLANK = "";
    private static final int INFINITY = 65536;
    private final String[] subjectsListArray;

    private JLabel textFilterLabel;
    private JLabel ignoreProbesLabel;

    public static JButton ignoreResponseTimeBelowUpdateButton;
    public static JButton ignoreResponseTimeAboveUpdateButton;

    private JList subjectList;

    private static JCheckBox ignoreNonExpItemsCheckBox;
    private static JCheckBox ignoreReactionTimeAboveCheckBox;
    private static JCheckBox showOnlySelectedSubjectsCheckBox;
    private static JCheckBox ignoreReactionTimeBelowCheckBox;
    private static JCheckBox filterIncorrectResponseCheckBox;

    public static IntegerField lowerLimitResponseTimeTextField;
    public static IntegerField upperLimitResponseTimeTextField;
    private JTextField textFilterTextField;
    private JTextField ignoreProbesTextField;

    private JScrollPane subjectListScrollPane;

    private final JPanel filterControlsPanel;
    private TablePanelHandler tablePanelHandlerObject;
    private final FilterControlsFrameHandler filterControlsFrameHandler;

    public FilterControlsPanelHandler(FilterControlsFrameHandler filterControlsFrameHandler,
	    TablePanelHandler tablePanelHandlerObject) {
	this.filterControlsFrameHandler = filterControlsFrameHandler;
	this.tablePanelHandlerObject = tablePanelHandlerObject;
	filterControlsPanel = new JPanel();
	GroupLayout filterControlsPanelLayout = new GroupLayout(filterControlsPanel);
	filterControlsPanel.setLayout(filterControlsPanelLayout);

	tablePanelHandlerObject.getTableColumnsList();
	subjectsListArray = tablePanelHandlerObject.getSubjectList();

	initComponents();
	addComponents();

    }

    private void addComponents() {
	LayoutConstraintsManager layoutConstraintsManager = LayoutConstraintsManager.getLayoutConstraintsManager(this
		.getClass().getResourceAsStream(FILTER_CONTROLS_PANEL_LAYOUT_XML_FILE));
	LayoutManager panelLayout = layoutConstraintsManager.createLayout("panel", this);
	filterControlsPanel.setLayout(panelLayout);
	filterControlsPanel.setFocusable(true);

	// add components
	filterControlsPanel.add(ignoreProbesLabel, "ignoreProbesLabel");
	filterControlsPanel.add(ignoreProbesTextField, "ignoreProbesTextField");

	filterControlsPanel.add(textFilterTextField, "textFilterTextField");
	filterControlsPanel.add(subjectListScrollPane, "subjectList");

	filterControlsPanel.add(ignoreNonExpItemsCheckBox, "ignoreNonExpItemsCheckBox");
	filterControlsPanel.add(ignoreReactionTimeAboveCheckBox, "ignoreResponseTimeAboveCheckBox");
	filterControlsPanel.add(textFilterLabel, "textFilterLabel");

	filterControlsPanel.add(showOnlySelectedSubjectsCheckBox, "showOnlySelectedSubjectsCheckBox");
	filterControlsPanel.add(ignoreReactionTimeBelowCheckBox, "ignoreResponseTimeBelowCheckBox");
	filterControlsPanel.add(filterIncorrectResponseCheckBox, "filterIncorrectResponseCheckBox");

	filterControlsPanel.add(lowerLimitResponseTimeTextField, "lowerLimitResponseTimeTextField");
	filterControlsPanel.add(upperLimitResponseTimeTextField, "upperLimitResponseTimeTextField");

	filterControlsPanel.add(ignoreResponseTimeBelowUpdateButton, "ignoreResponseTimeBelowUpdateButton");
	filterControlsPanel.add(ignoreResponseTimeAboveUpdateButton, "ignoreResponseTimeAboveUpdateButton");

	// control configuration
	// ignoreProbesCheckBox.addActionListener(this);

	// ignoreProbesTextField.setEnabled(false);
	subjectList.setEnabled(false);

	ignoreNonExpItemsCheckBox.addActionListener(this);
	ignoreReactionTimeAboveCheckBox.addActionListener(this);
	showOnlySelectedSubjectsCheckBox.addActionListener(this);
	ignoreReactionTimeBelowCheckBox.addActionListener(this);
	filterIncorrectResponseCheckBox.addActionListener(this);
	ignoreResponseTimeBelowUpdateButton.addActionListener(this);
	ignoreResponseTimeAboveUpdateButton.addActionListener(this);

	lowerLimitResponseTimeTextField.setEnabled(false);
	upperLimitResponseTimeTextField.setEnabled(false);
	ignoreResponseTimeBelowUpdateButton.setEnabled(false);
	ignoreResponseTimeAboveUpdateButton.setEnabled(false);

	textFilterTextField.setFont(new Font("Italic font", Font.ITALIC, 12));
	textFilterLabel.setFont(new Font("Search Font", Font.ITALIC + Font.BOLD, 12));

	ignoreProbesTextField.setFont(new Font("Italic font", Font.ITALIC, 12));
	ignoreProbesLabel.setFont(new Font("Search Font", Font.ITALIC + Font.BOLD, 12));

    }

    private void initComponents() {

	// here are declarations for the controls you created
	textFilterLabel = new JLabel("Search Pattern:");

	textFilterTextField = new JTextField(SEARCH_TIP);
	ignoreProbesTextField = new JTextField(IGNORE_PROBES);
	lowerLimitResponseTimeTextField = new IntegerField(4);

	ignoreProbesLabel = new JLabel("Ignore Probes");
	ignoreNonExpItemsCheckBox = new JCheckBox("Ignore Non-Experimental Items");
	ignoreReactionTimeAboveCheckBox = new JCheckBox("Ignore Reaction Time Above:");
	showOnlySelectedSubjectsCheckBox = new JCheckBox("Show Selected Subjects");
	ignoreReactionTimeBelowCheckBox = new JCheckBox("Ignore Reaction Time Below:");
	filterIncorrectResponseCheckBox = new JCheckBox("Filter Incorrect Respose");
	subjectList = new JList(subjectsListArray);
	subjectList.addListSelectionListener(new SubjectListSelectionListener(tablePanelHandlerObject));
	subjectListScrollPane = new JScrollPane(subjectList);
	upperLimitResponseTimeTextField = new IntegerField(4);

	ignoreResponseTimeBelowUpdateButton = new JButton("Update");
	ignoreResponseTimeAboveUpdateButton = new JButton("Update");

	// configure text field filter
	textFilterTextField.addFocusListener(this);
	textFilterTextField.setForeground(Color.GRAY);
	textFilterTextField.getDocument().addDocumentListener(
		new SearchTextChangeListener(tablePanelHandlerObject, this));
	filterIncorrectResponseCheckBox.requestFocus();

	// configure ignore probes filter
	ignoreProbesTextField.addFocusListener(this);
	ignoreProbesTextField.setForeground(Color.GRAY);
	ignoreProbesTextField.getDocument().addDocumentListener(
		new ProbeFilterTextChangeListener(tablePanelHandlerObject, this));
	filterIncorrectResponseCheckBox.requestFocus();

    }

    protected String getTextFilterText() {
	return this.textFilterTextField.getText();
    }

    protected String getIgnoreProbesText() {
	return this.ignoreProbesTextField.getText();
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
	Object eventSource = ae.getSource();

	/***************************************************************************
	 * CheckBoxes - Start
	 * *************************************************************************/

	/* Ignore reaction time below checkbox action listener - lower limit */
	if (eventSource.equals(ignoreReactionTimeBelowCheckBox)) {
	    if (ignoreReactionTimeBelowCheckBox.isSelected()) {
		this.lowerLimitResponseTimeTextField.setEnabled(true);
		this.lowerLimitResponseTimeTextField.setBackground(Color.YELLOW);
		this.ignoreResponseTimeBelowUpdateButton.setEnabled(true);
	    } else {
		this.lowerLimitResponseTimeTextField.setEnabled(false);
		this.ignoreResponseTimeBelowUpdateButton.setEnabled(false);
		this.lowerLimitResponseTimeTextField.setText(BLANK);
		this.lowerLimitResponseTimeTextField.setBackground(Color.WHITE);
		/*
		 * int reactionTimeColumnIndex = tablePanelHandlerObject
		 * .getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
		 */
		int reactionTimeColumnIndex = ConcreteTableModelListener
			.getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
		this.tablePanelHandlerObject.rectionTimeFilter(reactionTimeColumnIndex, 0, false);

	    }

	}

	/* Ignore reaction time checkbox action listener - Upper limit */
	if (eventSource.equals(ignoreReactionTimeAboveCheckBox)) {

	    if (ignoreReactionTimeAboveCheckBox.isSelected()) {
		this.upperLimitResponseTimeTextField.setEnabled(true);
		this.ignoreResponseTimeAboveUpdateButton.setEnabled(true);
		this.upperLimitResponseTimeTextField.setBackground(Color.YELLOW);

		// the rest will be handled either in keyListener or document listener
	    } else {
		this.upperLimitResponseTimeTextField.setEnabled(false);
		this.ignoreResponseTimeAboveUpdateButton.setEnabled(false);

		this.upperLimitResponseTimeTextField.setText(BLANK);
		this.upperLimitResponseTimeTextField.setBackground(Color.WHITE);
		/*
		 * int reactionTimeColumnIndex = tablePanelHandlerObject
		 * .getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
		 */
		int reactionTimeColumnIndex = ConcreteTableModelListener
			.getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
		this.tablePanelHandlerObject.rectionTimeFilter(reactionTimeColumnIndex, INFINITY, true);

	    }

	}

	/* Show only selected subject checkbox action result */
	if (eventSource.equals(showOnlySelectedSubjectsCheckBox)) {
	    if (showOnlySelectedSubjectsCheckBox.isSelected()) {
		this.subjectList.setEnabled(true);
		this.subjectList.setSelectionInterval(0, subjectList.getLastVisibleIndex());
		this.subjectList.setBackground(Color.YELLOW);
	    } else {
		this.subjectList.setEnabled(false);
		this.subjectList.clearSelection();
		// this.subjectList.removeAll();
		this.subjectList.setBackground(Color.WHITE);
	    }

	}

	/* filter incorrect response checkbox - action result */
	if (eventSource.equals(filterIncorrectResponseCheckBox)) {
	    System.out.println("filterIncorrectResponseCheckBox");
	    if (filterIncorrectResponseCheckBox.isSelected()) {
		// int userResponseColumnIndex =
		// tablePanelHandlerObject.getColumnIndexByName(RESPONSE_COLUMN_IDENTIFIER);
		int userResponseColumnIndex = ConcreteTableModelListener
			.getColumnIndexByName(RESPONSE_COLUMN_IDENTIFIER);

		// int expectedResponseColumnIndex = tablePanelHandlerObject
		// .getColumnIndexByName(CORRECT_RESPONSE_COLUMN_IDENTIFIER);
		int expectedResponseColumnIndex = ConcreteTableModelListener
			.getColumnIndexByName(CORRECT_RESPONSE_COLUMN_IDENTIFIER);
		this.tablePanelHandlerObject.incorrectResponseFilter(userResponseColumnIndex,
			expectedResponseColumnIndex);
	    } else {
		this.tablePanelHandlerObject.incorrectResponseFilter(0, 0);
	    }
	}

	/* filter non experimental items */
	if (eventSource.equals(ignoreNonExpItemsCheckBox)) {
	    String initialInput = null;
	    String userInput = null;
	    if (ignoreNonExpItemsCheckBox.isSelected()) {
		initialInput = tablePanelHandlerObject.getColumnNameByItemName(UtilityConstants.EXPERIMENTAL_ITEM);
		userInput = JOptionPane.showInputDialog(
			"Confirm the column name for exp items\n or type a different name", initialInput);
		// int expColumnIndex = this.tablePanelHandlerObject.getColumnIndexByName(userInput);
		int expColumnIndex = ConcreteTableModelListener.getColumnIndexByName(userInput);
		this.tablePanelHandlerObject.columnTextFilter(
			TablePanelHandler.EXPERIMENTAL_PARAMETER_IDENTIFIER_STRING, expColumnIndex,
			tablePanelHandlerObject.getColumnTextFilterIndex(NON_EXP_ITEMS_FILTER));
	    } else {
		// int expColumnIndex = this.tablePanelHandlerObject.getColumnIndexByName(userInput);
		int expColumnIndex = ConcreteTableModelListener.getColumnIndexByName(userInput);
		this.tablePanelHandlerObject.columnTextFilter("", expColumnIndex,
			tablePanelHandlerObject.getColumnTextFilterIndex(NON_EXP_ITEMS_FILTER));
	    }
	}

	/***************************************************************************
	 * CheckBoxes - End
	 * *************************************************************************/

	/***************************************************************************
	 * Buttons - Start
	 * *************************************************************************/
	if (eventSource.equals(this.ignoreResponseTimeAboveUpdateButton)) {
	    System.out.println("Reaction time above filter activated");
	    int upperLimit = Integer.valueOf(this.upperLimitResponseTimeTextField.getText());
	    // int reactionTimeColumnIndex =
	    // tablePanelHandlerObject.getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
	    int reactionTimeColumnIndex = ConcreteTableModelListener
		    .getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
	    this.tablePanelHandlerObject.rectionTimeFilter(reactionTimeColumnIndex, upperLimit, true);
	}

	if (eventSource.equals(this.ignoreResponseTimeBelowUpdateButton)) {
	    System.out.println("Reaction time below filter activated");
	    int lowerLimit = Integer.valueOf(this.lowerLimitResponseTimeTextField.getText());
	    // int reactionTimeColumnIndex =
	    // tablePanelHandlerObject.getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
	    int reactionTimeColumnIndex = ConcreteTableModelListener
		    .getColumnIndexByName(REACTION_TIME_COLUMN_IDENTIFIER);
	    this.tablePanelHandlerObject.rectionTimeFilter(reactionTimeColumnIndex, lowerLimit, false);
	}
	/***************************************************************************
	 * Buttons - End
	 * *************************************************************************/

    }

    @Override
    public JPanel getPanel() {
	return filterControlsPanel;
    }

    @Override
    public void focusGained(FocusEvent event) {
	Object source = event.getSource();
	if (source.equals(this.textFilterTextField)) {
	    if (this.textFilterTextField.getText().equals(SEARCH_TIP)) {
		this.textFilterTextField.setText(BLANK);
	    }

	    this.textFilterTextField.setForeground(Color.BLACK);
	} else if (source.equals(this.ignoreProbesTextField)) {
	    if (this.ignoreProbesTextField.getText().equals(IGNORE_PROBES)) {
		this.ignoreProbesTextField.setText(BLANK);
	    }
	    this.ignoreProbesTextField.setForeground(Color.BLACK);
	}

    }

    @Override
    public void focusLost(FocusEvent event) {
	Object source = event.getSource();
	if (source.equals(this.textFilterTextField)) {
	    if (this.textFilterTextField.getText().equals(BLANK)) {
		this.textFilterTextField.setText(SEARCH_TIP);
	    }
	    this.textFilterTextField.setForeground(Color.GRAY);

	} else if (source.equals(this.ignoreProbesTextField)) {
	    if (this.ignoreProbesTextField.getText().equals(BLANK)) {
		this.ignoreProbesTextField.setText(IGNORE_PROBES);
	    }
	    this.ignoreProbesTextField.setForeground(Color.GRAY);
	}

    }

    protected boolean hasTextSearchActive() {
	return this.textFilterTextField.hasFocus();
    }

    protected boolean hasProbeSearchActive() {
	return this.ignoreProbesTextField.hasFocus();
    }

    /**
     * 
     */
    public static void checkFilterIncorrectResponseCheckBox() {
	filterIncorrectResponseCheckBox.doClick();
    }

    /**
     * 
     */
    public static void checkIgnoreNonExpItemsCheckBox() {
	ignoreNonExpItemsCheckBox.doClick();
    }

    /**
     * 
     */
    public static void checkIgnoreReactionTimeAboveCheckBox() {
	ignoreReactionTimeAboveCheckBox.doClick();
    }

    /**
     * 
     */
    public static void checkIgnoreReactionTimeBelowCheckBox() {
	ignoreReactionTimeBelowCheckBox.doClick();
    }

}
